package com.cn.demo.springboot.quartz.service;

import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.quartz.CronScheduleBuilder;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.Trigger.TriggerState;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cn.demo.springboot.quartz.bo.InitJobBo;
import com.cn.demo.springboot.quartz.config.InitJob;
//@Transactional
@Service
//@Slf4j
public final class TriggerUtilImpl implements ITriggerUtil {
	private final static Logger log = LoggerFactory.getLogger(TriggerUtilImpl.class);
	@Autowired
	private Scheduler scheduler;

	@Autowired
	private IJobService jobService;
	
	
	private JobDetail buildJobDetail(InitJobBo initJob) {
		Job newInstance = null;
		try {
			newInstance = (Job) Class.forName(initJob.getClassName()).newInstance();
		} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
			log.error(e.getMessage());
			throw new RuntimeException(e.getMessage());
		}
		JobDetail job = newJob(newInstance.getClass()).withIdentity(initJob.getTaskName(), initJob.getTaskGroup()).build();
		return job;
	}

	@Override
	public void updateCron(String newCron, String jobId) throws SchedulerException {
		
		log.debug("修改Cron开始-------------------------1.1,newCron={},jobId={}", newCron, jobId);

		InitJobBo initJob = jobService.getInitJobBoById(jobId);

		if (initJob == null) {
			log.error("修改Cron-------------------------jobId无效,jobId = {}", jobId);
			throw new RuntimeException("修改失败");
		}

		initJob.setTaskCron(newCron);

		log.info("修改Cron-------------------------1.2,initJob={}", initJob);
		if (initJob.getTaskRun()) {

			log.debug("修改Cron-------------------------1.3,");

			Trigger trigger = scheduler.getTrigger(
					new TriggerKey(initJob.getTaskName() + InitJob.TRIGGER, initJob.getTaskGroup() + InitJob.TRIGGER));

			Trigger newTrigger = buildTrigger(initJob);

			Date rescheduleJob = null;

			if (trigger != null) {
				log.debug("修改Cron-------------------------1.4.1--------从新安排任务");
				rescheduleJob = scheduler.rescheduleJob(trigger.getKey(), newTrigger);
			} else {
				log.debug("修改Cron-------------------------1.4.2--------安排新任务");
				rescheduleJob = scheduler.scheduleJob(buildJobDetail(initJob), newTrigger);
				scheduler.resumeTrigger(newTrigger.getKey());
				//scheduler.start();
			}

			if (rescheduleJob == null) {
				log.error("修改Cron-------------------------1.5--------触发器无法启动");
				throw new RuntimeException("触发器无法启动,修改失败");
			}

		}
		log.debug("修改Cron-------------------------1.6------------------保存数据，initJob = {}",initJob);
		//保存
		saveInitJobBo(initJob);
	}
	@Override
	public void updateRunStatus(Boolean taskRun, String jobId) throws SchedulerException{

		log.debug("修改taskRun开始-------------------------1.1,taskRun={},jobId={}", taskRun, jobId);
		
		InitJobBo initJob = jobService.getInitJobBoById(jobId);
		
		if (initJob == null) {
			log.error("修改taskRun-------------------------jobId无效,jobId = {}", jobId);
			throw new RuntimeException("修改失败");
		}
		
		initJob.setTaskRun(taskRun);
		
		TriggerKey triggerKey = new TriggerKey(initJob.getTaskName() + InitJob.TRIGGER,
				initJob.getTaskGroup() + InitJob.TRIGGER);
		boolean b = scheduler.checkExists(triggerKey);
		
		log.debug("修改taskRun-------------------------1.2,b={}", b);
		
		if (b) {
			
			TriggerState triggerState = scheduler.getTriggerState(triggerKey);
			
			log.debug("修改taskRun-------------------------1.3,triggerState={}", triggerState);
			
			if (taskRun) {

				if (triggerState == TriggerState.BLOCKED || triggerState == TriggerState.COMPLETE || triggerState == TriggerState.NORMAL) {
					
				} else if (triggerState == TriggerState.PAUSED) {
					
					Trigger newTrigger = buildTrigger(initJob);
					scheduler.rescheduleJob(triggerKey, newTrigger);
					scheduler.resumeTrigger(newTrigger.getKey());
					
				} else  {
					//(triggerState == TriggerState.ERROR || triggerState == TriggerState.NONE)
					throw new RuntimeException("未知状态！");
				}
				
			} else {
				if (triggerState == TriggerState.BLOCKED || triggerState == TriggerState.COMPLETE || triggerState == TriggerState.NORMAL) {
					scheduler.pauseTrigger(triggerKey);
				} else if (triggerState == TriggerState.PAUSED) {
					
				} else  {
					//(triggerState == TriggerState.ERROR || triggerState == TriggerState.NONE)
					throw new RuntimeException("未知状态！");
				}
			}
			
			
		} else {
			if (taskRun) {
				Trigger buildTrigger = buildTrigger(initJob);
				scheduler.scheduleJob(buildJobDetail(initJob), buildTrigger);
				scheduler.resumeTrigger(buildTrigger.getKey());
			} else {

			}
		}
		//保存
		saveInitJobBo(initJob);
	}
	/**
	 * tj
	 * 2018年12月3日 上午11:56:10
	 */
	@Override
	public void nowExecute(String jobId)  throws SchedulerException{
		log.debug("nowExecute开始-------------------------1.1,jobId={}", jobId);
		
		InitJobBo initJob = jobService.getInitJobBoById(jobId);
		
		if (initJob == null) {
			log.error("nowExecute-------------------------jobId无效,jobId = {}", jobId);
			throw new RuntimeException("nowExecute失败");
		}

		
		TriggerKey triggerKey = new TriggerKey(initJob.getTaskName() + InitJob.TRIGGER,
				initJob.getTaskGroup() + InitJob.TRIGGER);
		boolean b = scheduler.checkExists(triggerKey);
		
		if(b) {
			JobKey jobKey = scheduler.getTrigger(triggerKey).getJobKey();
			scheduler.triggerJob(jobKey);
		}else {
			log.error("nowExecute-------------------------triggerKey无效");
			throw new RuntimeException("需要先开启任务");
		}

	}
	private Trigger buildTrigger(InitJobBo initJob) {
		return newTrigger()
				.withIdentity(initJob.getTaskName() + InitJob.TRIGGER, initJob.getTaskGroup() + InitJob.TRIGGER)
				.startNow().withSchedule(CronScheduleBuilder.cronSchedule(initJob.getTaskCron())).build();
	}
	
	private void saveInitJobBo(InitJobBo initJob){
		List<InitJobBo> bos = new ArrayList<InitJobBo>();
		bos.add(initJob);
		jobService.saveAll(bos);
	} 
}
